// Settings

var attempts = 3;
var hint_delay = 1500; // ms
var find_by = "name"; // name | code | atomic | molar
var timer = 30; // seconds
var grade_size = 5;
var round_count = 5;

// End of settings

var winScroller;
var currentAttempts = attempts;
var current = "";
var elements = new Hash();
var timerFx;
var timerInst;
var stats = {
	wrong: {
		count: 0,
		indicator: null
	},
	good: {
		count: 0,
		indicator: null
	}
}
var findClass = "." + find_by;
var grade_step = grade_size / timer
var current_grade = 0.0

window.addEvent('domready', function() {
	if (Cookie.read('stored-guess-game'))
		loadStatistics(JSON.decode(Cookie.read('stored-guess-game')))
	timerFx = new Fx.Tween($("timeout-monitor"));
	winScroller = new Fx.Scroll(window);
	$('guess-type').addEvent('change', function() {
		var box = $('guess-type');
		find_by = box[box.selectedIndex].value;
		findClass = "." + find_by;
		initalize();
	});
	$$("div#mendeleev td").addEvent('click', guess);
	$('store-stats-to-cookie').addEvent('change', updateCookie);
	var statsDiv = $$("div#mendeleev div.statistics");
	stats.wrong.indicator = statsDiv.getFirst("div.wrong");
	stats.good.indicator = statsDiv.getFirst("div.good");
	$$("div#mendeleev div.statistics *").set('morph', {
		duration: 500,
		transition: Fx.Transitions.Bounce.easeOut,
		link: 'chain'
	});
	$("finish").addEvent('click', finish)
	initalize();
});
function getColor(good, wrong)
{
	var total = good+wrong;
	if (total == 0)
		return "rgb(100, 100, 100)";
	var calc = function(c, t) {
		return parseInt(2 * ((255 * c)/t));
	};
	return "rgb(" + calc(wrong, total) + ", " + calc(good, total) + ", 0)";
}
function initalize() {
	elements = new Hash();
	current = undefined;
	$$("div#mendeleev td *").setStyle("visibility", "visible");
	$$(findClass).each(function(el){
		elements.set(el.get('text'), el.parentNode);
		el.setStyle("visibility", "hidden");
	});
	newRound();
}
function guess()
{
	if (this == elements.get(current)) {
		incStats(stats.good);

		// Поскольку таймер рекурсивный, текущее его значение есть только в самой функции таймера и в поле 'timeout-monitor'
		// возможно, ради следующей строки был бы смысл переписать его с использованием глобальной переменной, но на скорость
		// выполнения это не сильно влияет, потому пока используется индусский вариант.
		current_grade += grade_step * $("timeout-monitor").get('text');
		$('grade').set('text', current_grade.toFixed(2));
		hint();
		this.store('good', this.retrieve('good', 0) + 1);
		(function(){newRound();}).delay(hint_delay);
	} else {
		this.store('wrong', this.retrieve('wrong', 0) + 1);
		if (decCurrentAttempts()) {
			incStats(stats.wrong);
			this.addClass("wrong-guess");
		} else {
			lose();
		}
	}
}
function lose()
{
	var correct = elements.get(current);
	correct.store('wrong', correct.retrieve('wrong', 0) + 1);
	incStats(stats.wrong);
	hint();
	(function(){newRound();}).delay(hint_delay);
}
function hint()
{
	disable();
	var correct = elements.get(current);
	scroll(correct);
	(function() {
		scroll($('guess-element-name'));
		enable();
	}).delay(hint_delay);
	$$("div#mendeleev td").addClass('shadow');
	correct.removeClass('shadow');
	correct.addClass('highlight');
	correct.getFirst(findClass).setStyle('visibility', 'visible')
}
function enable()
{
	$$("div#mendeleev td").addEvent('click', guess);
}
function disable()
{
	$$("div#mendeleev td").removeEvents('click');
	$clear(timerInst);
}
function scroll(toElement)
{
	if (!isVisible(toElement))
		winScroller.toElement(toElement);
}
function isVisible(element)
{
	var minVisible = window.getScroll().y;
	var maxVisible = minVisible + window.getHeight();
	var elCoords = element.getCoordinates();
	return elCoords.top >= minVisible && elCoords.top <= maxVisible;
}
function incStats(stat)
{
	stat.indicator.morph({'width': ++stat.count * 5 });
	stat.indicator.set('title', stat.count);
}

function newRound()
{
	$clear(timerInst);
	if (current)
		elements.get(current).getFirst(findClass).setStyle('visibility', 'hidden');
	removeClasses(["wrong-guess", "highlight", "shadow"]);
	
	if (round_count-- == 0) {
		finish();
		return;
	}
	
	current = elements.getKeys().getRandom();
	$("guess-element-name").set('text', current);
	setCurrentAttempts(attempts);
	setTimer(timer);
}
function setTimer(msecs)
{
	var monitor = $("timeout-monitor");
	if (monitor) monitor.set('text', msecs);
	timerFx.start('font-size', 23, 20);
	if (msecs <= 0)
		lose();
	else
		timerInst = (function(){setTimer(msecs-1)}).delay(1000);
}
function removeClasses(classes)
{
	for (var i = 0; i < classes.length; i++)
		$$("div#mendeleev ." + classes[i]).removeClass(classes[i]);
}
function decCurrentAttempts()
{
	setCurrentAttempts(currentAttempts - 1);
	return currentAttempts > 0;
}
function setCurrentAttempts(value)
{
	var monitor = $("attempts-counter");
	if (monitor) monitor.set('text', value);
	currentAttempts = value;
}
function updateCookie()
{
	var store = $('store-stats-to-cookie').checked;
	Cookie.dispose('stored-guess-game');
	if (store)
		Cookie.write('stored-guess-game', JSON.encode(getStatistics()), {duration: 365})
}
function getStatistics()
{
	var result = [];
	var code;
	var step = 0;
	$$('div#mendeleev td').each(function(cell) {
		if (!cell.innerHTML) // Skip empty cells
			return false;
		code = get(cell, 'code');
		var good = get(cell, 'good');
		var bad  = get(cell, 'wrong' );
		if (good || bad)
			result.push({'c': code, 'g': good, 'w': bad});
	});
	return result;
}
function loadStatistics(statsArray) {
	for (var i = 0; i < statsArray.length; i++) {
		var cell = getForCode(statsArray[i]['c']);
		cell.store('good', statsArray[i]['g']);
		cell.store('wrong', statsArray[i]['w']);
	}
}
function getForCode(code) {
	var els = $$('div#mendeleev td');
	for (var i = 0; i < els.length; i++) {
		cell = els[i];
		if (!cell.innerHTML)
			continue;
		if (get(cell, 'code') == code)
			return cell;
	}
	alert('fuck ' + code)
}
function get(cell, propertyName)
{
	if (propertyName == 'name'
	 || propertyName == 'code'
	 || propertyName == 'atomic'
	 || propertyName == 'molar') {
		return cell.getFirst("." + propertyName).get('text');
	} else if (propertyName == 'good'
		|| propertyName == 'wrong'){
		return cell.retrieve(propertyName, 0);
	}
}
function finish()
{
	disable();
	$('guess-type-select').setStyle('display', 'none');
	$$("div#mendeleev td " + findClass).setStyle('visibility', 'visible');
	$$("div#mendeleev td").each(function(el){
		el.setStyle('background-color', getColor(el.retrieve('good', 0), el.retrieve('wrong', 0)));
	});
	updateCookie();
	$('finish').setStyle('display', 'none');

}
